#include "ffplay_stater.h"


int packet_queue_init(PakcetQueue *q)
{
    int ret =0 ;

    memset(q,0,sizeof(PacketQueue));
    //创建cond 和 mutex
    q->mutex = SDL_CreateMutex();
    if(!q->mutex) {
        return ERRMUTEX;
    }

    q->cond = SDL_CreateCond();
    if(!q->cond) {
        return ERRCOND;
    }

    q->abort_request = 1;//退出请求
    return 0;
}

int frame_queue_init(PakcetQueue *q, FrameQueue *frm_queue, int maxsize )
{
    int ret = 0 ;
    memset(frm_queue,0,sizeof(FrameQueue));
    frm_queue->cond = SDL_CreateCond();
    if(!frm_queue->cond){
        return ERRCOND;
    }
    frm_queue->mutex = SDL_CreateMutex();
    if(!frm_queue->mutex){
        return ERRMUTEX;
    }
    frm_queue->pktq = q;
    //maxsize 待定
    frm_queue->max_size = FFMIN(FRAME_QUEUE_SIZE,maxsize);

    for(int i=0;i<frm_queue->max_size;i++){
        if(!(frm_queue->queue[i].frame = av_frame_alloc())){
            return ERRFRMAE;
        }
    }

    return ret;

}
//释放队列的数据,还有释放
int pakcet_queue_destroy(PakcetQueue *q)
{

    pakcet_queue_flush(q);
    SDL_DestroyCond(q->cond);
    SDL_DestroyMutex(q->mutex);
    return 0;
}

int pakcet_queue_flush(PakcetQueue *q)
{
    AVPacketList *a,*b;
    SDL_LockMutex(q->mutex);
    q->first_pkt;
    for(a=q->first_pkt;a;a=b){
        b=a->next;
        av_packet_unref(&(a->packet));
        av_freep(&a);
    }
    SDL_UnlockMutex(q->mutex);
    return 0;
}



int frame_queue_destroy(FrameQueue *q)
{
    frame_queue_flush(q);
    q->pktq=NULL;
    SDL_DestroyCond(q->cond);
    SDL_DestroyMutex(q->mutex);
    return 0;
}

int frame_queue_flush(FrameQueue *q)
{
    SDL_LockMutex(q->mutex);
    for(int i=0;i<q->max_size;i++){
        av_frame_unref((q->queue[i]).frame);
        av_frame_free(&((q->queue[i]).frame));
    }
    SDL_UnlockMutex(q->mutex);
    return 0;
}

int packet_queue_put(PakcetQueue *q, AVPacket *pkt)
{
    int ret =0 ;
    SDL_LockMutex(q->mutex);
    ret = packet_queue_put_l(q,pkt);
    SDL_UnlockMutex(q->mutex);
    if(ret<0 && pkt != &flush_pkt){
        av_packet_unref(pkt);
    }
    return ret;
}

int packet_queue_put_nullpkt(PakcetQueue *q,int stream_index)
{
    AVPacket *pkt;
    pkt->data=NULL;
    pkt->size=0;
    pkt->stream_index = stream_index;
    return packet_queue_put(q,pkt);
}

int packet_queue_put_l(PakcetQueue *q, AVPacket *pkt)
{
    int ret =0 ;
    AVPacketList *pkt_list;
    if(q->abort_request){
        return -1;
    }
    if(pkt->stream_index == vidindex){
        std::cout<<""<<std::endl;
    }
    pkt_list = (AVPacketList*) av_malloc(sizeof(AVPacketList));
    pkt_list->packet = *pkt;
    pkt_list->next = NULL;
    //pkt_list = (AVPacketList*) av_malloc(sizeof(AVPacketList));
    if(pkt == &flush_pkt){
        q->serial++;
    }
    pkt_list->serial = q->serial;
    //插入
    if(!q->last_pkt){
        q->first_pkt = pkt_list;
    }else{
        q->last_pkt->next = pkt_list;
    }
    q->last_pkt = pkt_list;

    //q->size += sizeof(pkt_list)+pkt_list->packet.size;管理的是packet的空间,所以只加上链表节点大小
    q->size += sizeof(*pkt_list)+pkt_list->packet.size;
    q->duration += pkt_list->packet.duration;
    q->nb_packets++;
    SDL_CondSignal(q->cond);
    return ret;
}

int packet_queue_start(PakcetQueue *q)
{
    SDL_LockMutex(q->mutex);

    q->abort_request = 0;
    //还需要插入一个flushpkt
    packet_queue_put_l(q, &flush_pkt);
    SDL_UnlockMutex(q->mutex);
}

int packet_queue_get(PakcetQueue *q, AVPacket *pkt, int block, int *pkt_serial)
{
    AVPacketList *pkt1= NULL;
    int ret = 0 ;
    SDL_LockMutex(q->mutex);
    int cont=0;
    for(;;){
        pkt1 = q->first_pkt;
        //读取到packet
        if(pkt1){
            q->first_pkt = pkt1->next;
            q->nb_packets--;
            //可能有问题,需要考虑一下
            if(q->nb_packets == 0){
                q->last_pkt = NULL;
            }
            q->duration -= pkt1->packet.duration;
            q->size -= (sizeof(*pkt1)+pkt1->packet.size);
            *pkt = pkt1->packet;
            if(pkt_serial){
                *pkt_serial = pkt1->serial;
            }
            av_free(pkt1);
            ret = 1;
            //if(pkt->stream_index == )
            break;
         //非阻塞
        }else if(!block){
            ret = -(1+cont);
            break;
          //阻塞
        }else{
            SDL_CondWait(q->cond,q->mutex);
        }
    }
    SDL_UnlockMutex(q->mutex);
    return ret;

}

//typedef struct FrameQueue {
//    Frame	queue[FRAME_QUEUE_SIZE];        // FRAME_QUEUE_SIZE  最大size, 数字太大时会占用大量的内存，需要注意该值的设置
//    int		rindex;                         // 读索引。待播放时读取此帧进行播放，播放后此帧成为上一帧
//    int		windex;                         // 写索引
//    int		size;                           // 当前总帧数
//    int		max_size;                       // 可存储最大帧数
//    SDL_mutex	*mutex;                     // 互斥量
//    SDL_cond	*cond;                      // 条件变量
//    PacketQueue	*pktq;                      // 数据包缓冲队列
//}FrameQueue;



int frame_queue_get_wirtable(FrameQueue *q, Frame **frame)
{
    SDL_LockMutex(q->mutex);
    while(q->size >= q->max_size && !q->pktq->abort_request){
        SDL_CondWait(q->cond,q->mutex);
    }
    SDL_UnlockMutex(q->mutex);

    if(q->pktq->abort_request){
        return -1;
    }
    *frame =  &q->queue[q->windex];
    return 0;

}

int frame_queue_next_wirte(FrameQueue *q)
{

    SDL_LockMutex(q->mutex);
    q->windex = ++q->windex % q->max_size;
    q->size++;
    SDL_CondSignal(q->cond);
    SDL_UnlockMutex(q->mutex);



}

void frame_queue_free(Frame *f){
    av_frame_unref(f->frame);

}
//int frame_queue_write(FrameQueue *q, AVFrame *frame)
//{
//    int ret =0 ;
//    Frame* f=NULL;
//    ret = frame_queue_get_wirtable(q,f);
//    f->duration+=frame->si


//}

//typedef struct SDL_AudioSpec
//{
//    int freq;                   /**< DSP frequency -- samples per second */
//    SDL_AudioFormat format;     /**< Audio data format */
//    Uint8 channels;             /**< Number of channels: 1 mono, 2 stereo */
//    Uint8 silence;              /**< Audio buffer silence value (calculated) */
//    Uint16 samples;             /**< Audio buffer size in samples (power of 2) */
//    Uint16 padding;             /**< Necessary for some compile environments */
//    Uint32 size;                /**< Audio buffer size in bytes (calculated) */
//    SDL_AudioCallback callback;
//    void *userdata;
//} SDL_AudioSpec;


int frame_queue_get_readable(FrameQueue *q, Frame **frame)
{
    SDL_LockMutex(q->mutex);
    while(q->size<=0 && !q->pktq->abort_request){
        SDL_CondWait(q->cond,q->mutex);
    }
    SDL_UnlockMutex(q->mutex);

    if(q->pktq->abort_request){
        return -1;
    }

    *frame = &q->queue[(q->rindex+q->shown)%q->max_size];

    return 1;

}

int frame_queue_next_read(FrameQueue *q)
{
   int ret =0;
   if(!q->shown){
       q->shown = 1;
       return 0;
   }


    frame_queue_free(&q->queue[q->rindex]);

    q->queue[q->rindex];
    SDL_LockMutex(q->mutex);
    q->size--;
    q->rindex++;
    if(q->rindex == q->max_size){
        q->rindex = 0;
    }
    SDL_CondSignal(q->cond);
    SDL_UnlockMutex(q->mutex);
    return ret;

}

int frame_queue_nb_remaining(FrameQueue *q)
{
    return q->size;
}

Frame *frame_queue_get(FrameQueue *q)
{
    return &q->queue[(q->rindex+q->shown)%q->max_size];
}

double get_duration(Frame *vp, Frame *lastvp)
{
    if(vp->serial == lastvp->serial){
        return vp->pts - lastvp->pts;
    }else{
        return 0.0;
    }

}

int frame_queue_get_last_readable(FrameQueue *q, Frame **frame)
{
    *frame = &q->queue[(q->rindex+q)%q->max_size];
}

Frame *frame_queue_get_last(FrameQueue *q)
{
     return &q->queue[(q->rindex)%q->max_size];
}

Frame *frame_queue_get_next(FrameQueue *q)
{
     return &q->queue[(q->rindex+q->shown+1)%q->max_size];
}
